#include <string.h>
#include <time.h>
#include "defs.h"
-#include "jeeps/gpsmath.h"
+#include "session.h"
-#define MYNAME "tr7"
+#define MYNAME "mapasia"
-#define TR7_TRACK_MAGIC 0x223eadb
+#define TR7_TRACK_MAGIC 0x223EADB
+
+#define TR7_S_SIZE 32
#define TR7_S_YEAR 0
#define TR7_S_MONTH 2
#define TR7_S_VALID 28
#define TR7_S_FIX 29
+static gbfile *fin, *fout;
+static const waypoint *wpt_tmp;
+static const route_head *trk_tmp;
+static int course_tmp, speed_tmp;
+
static
arglist_t tr7_args[] = {
ARG_TERMINATOR
};
-static gbfile *fin;
/*******************************************************************************
* %%% global callbacks called by gpsbabel main process %%% *
}
while (! gbfeof(fin)) {
- unsigned char buff[32];
+ unsigned char buff[TR7_S_SIZE];
+ double lat, lon;
+ struct tm tm;
+ waypoint *wpt;
+
gbfread(buff, 1, sizeof(buff), fin);
- if (buff[0] == 0xD8) {
- double lat, lon;
- struct tm tm;
- waypoint *wpt;
-
- memset(&tm, 0, sizeof(tm));
-
- lat = (double)le_read32(&buff[TR7_S_LAT]) / 1000000.0;
- lon = (double)le_read32(&buff[TR7_S_LON]) / 1000000.0;
- if ((fabs(lat) > 90) || (fabs(lon) > 180)) {
- trk = NULL;
- continue;
- }
-
- tm.tm_year = le_read16(&buff[TR7_S_YEAR]) - 1900;
- tm.tm_mon = buff[TR7_S_MONTH] - 1;
- tm.tm_mday = buff[TR7_S_DAY];
-
- tm.tm_hour = buff[TR7_S_HOUR];
- tm.tm_min = buff[TR7_S_MIN];
- tm.tm_sec = buff[TR7_S_SEC];
-
- wpt = waypt_new();
-
- wpt->latitude = lat;
- wpt->longitude = lon;
+
+ memset(&tm, 0, sizeof(tm));
+
+ lat = (double)le_read32(&buff[TR7_S_LAT]) / 1000000.0;
+ lon = (double)le_read32(&buff[TR7_S_LON]) / 1000000.0;
+
+ if ((fabs(lat) > 90) || (fabs(lon) > 180)) { /* that really happens */
+ trk = NULL;
+ continue;
+ }
+
+ tm.tm_year = le_read16(&buff[TR7_S_YEAR]);
+ tm.tm_mon = buff[TR7_S_MONTH];
+ tm.tm_mday = buff[TR7_S_DAY];
+ tm.tm_hour = buff[TR7_S_HOUR];
+ tm.tm_min = buff[TR7_S_MIN];
+ tm.tm_sec = buff[TR7_S_SEC];
+
+ wpt = waypt_new();
+
+ wpt->latitude = lat;
+ wpt->longitude = lon;
+
+ /* create only valid timestamps */
+ if (tm.tm_mday && (tm.tm_mday <= 31) && tm.tm_mon && (tm.tm_mon <= 12) && (tm.tm_year > 1970)) {
+ tm.tm_year -= 1900;
+ tm.tm_mon -= 1;
wpt->creation_time = mkgmtime(&tm);
- WAYPT_SET(wpt, course, 360 - le_read16(&buff[TR7_S_COURSE]));
- WAYPT_SET(wpt, speed, (double)le_read16(&buff[TR7_S_SPEED]) / 3.6);
-#if 0
- /* unsure items */
- wpt->fix = buff[TR7_S_FIX];
- if (buff[TR7_S_VALID] != 'A') {
- waypt_free(wpt);
- continue;
- }
+ }
+
+ WAYPT_SET(wpt, course, 360 - le_read16(&buff[TR7_S_COURSE]));
+ WAYPT_SET(wpt, speed, KPH_TO_MPS(le_read16(&buff[TR7_S_SPEED])));
+
+#if 0 /* unsure, not validated items */
+ wpt->fix = buff[TR7_S_FIX];
+ if (buff[TR7_S_VALID] != 'A') {
+ waypt_free(wpt);
+ continue;
+ }
+#endif
+ if (waypt_speed(prev, wpt) > 9999.9) { /* filter out some bad trackpoints */
+ waypt_free(wpt);
+ continue;
+ }
+
+ if (prev) { /* other track or bad timestamp */
+ if (wpt->creation_time && (prev->creation_time > wpt->creation_time)) trk = NULL;
+ else if (waypt_distance(prev, wpt) > 9999.9) trk = NULL;
+ }
+
+ if (! trk) {
+ trk = route_head_alloc();
+ track_add_head(trk);
+ }
+ track_add_wpt(trk, wpt);
+ prev = wpt;
+ }
+}
+
+/**************************************************************************/
+
+static void
+tr7_disp_track_head_cb(const route_head *trk)
+{
+ wpt_tmp = NULL;
+}
+
+static void
+tr7_disp_waypt_cb(const waypoint *wpt)
+{
+ unsigned char buff[TR7_S_SIZE];
+ struct tm tm;
+ double speed, course;
+
+ memset(buff, 0, sizeof(buff));
+
+ le_write32(&buff[TR7_S_LON], (int)(wpt->longitude * 1000000.0));
+ le_write32(&buff[TR7_S_LAT], (int)(wpt->latitude * 1000000.0));
+
+ if WAYPT_HAS(wpt, course) course = wpt->course;
+ else if (wpt_tmp != NULL) course = waypt_course(wpt_tmp, wpt);
+ else course = -1;
+ if (course >= 0) le_write16(&buff[TR7_S_COURSE], (int)(360 - course));
+
+ if (wpt->creation_time) {
+ tm = *gmtime(&wpt->creation_time);
+
+ le_write16(&buff[TR7_S_YEAR], tm.tm_year + 1900);
+ buff[TR7_S_MONTH] = tm.tm_mon + 1;
+ buff[TR7_S_DAY] = tm.tm_mday;
+ buff[TR7_S_HOUR] = tm.tm_hour;
+ buff[TR7_S_MIN] = tm.tm_min;
+ buff[TR7_S_SEC] = tm.tm_sec;
+
+ if WAYPT_HAS(wpt, speed) speed = wpt->speed;
+ else if (wpt_tmp != NULL) speed = waypt_speed(wpt_tmp, wpt);
+ else speed = -1;
+ if (speed >= 0) le_write16(&buff[TR7_S_SPEED], (int)MPS_TO_KPH(speed));
+ }
+ buff[TR7_S_VALID] = 'A'; /* meaning unknown */
+
+#if 0 /* not validated */
+ if (wpt->fix != fix_unknown) buff[TR7_S_FIX] = wpt->fix;
#endif
- if (waypt_speed(prev, wpt) > 9999.9) {
- waypt_free(wpt);
- continue;
- }
-
- if (! trk) {
- trk = route_head_alloc();
- track_add_head(trk);
- }
- track_add_wpt(trk, wpt);
- prev = wpt;
+ gbfwrite(buff, 1, sizeof(buff), fout);
+
+ wpt_tmp = wpt;
+}
+
+static void
+tr7_wr_init(const char *fname)
+{
+ fout = gbfopen_le(fname, "wb", MYNAME);
+ gbfputint32(TR7_TRACK_MAGIC, fout);
+}
+
+static void
+tr7_check_after_read_head_cb(const route_head *trk)
+{
+ trk_tmp = trk;
+ course_tmp = 0;
+ speed_tmp = 0;
+}
+
+static void
+tr7_check_after_read_wpt_cb(const waypoint *wpt)
+{
+ if (wpt->speed != 0) speed_tmp = 1;
+ if (wpt->course != 360.0) course_tmp = 1;
+}
+
+static void
+tr7_check_after_read_trailer_cb(const route_head *trk)
+{
+ queue *elem, *tmp;
+ QUEUE_FOR_EACH((queue *)&trk->waypoint_list, elem, tmp) {
+ waypoint *wpt = (waypoint *)elem;
+ if (speed_tmp == 0) WAYPT_UNSET(wpt, speed);
+ if (course_tmp == 0) {
+ WAYPT_UNSET(wpt, course);
+ wpt->course = 0;
}
}
}
+static void
+tr7_wr_deinit(void)
+{
+ track_disp_session(curr_session(),
+ tr7_check_after_read_head_cb,
+ tr7_check_after_read_trailer_cb,
+ tr7_check_after_read_wpt_cb);
+ gbfclose(fout);
+}
+
+static void
+tr7_write(void)
+{
+ track_disp_all(tr7_disp_track_head_cb, NULL, tr7_disp_waypt_cb);
+}
+
/**************************************************************************/
-ff_vecs_t mapasia_tr7_vecs = { /* currently we can only read tracks */
+ff_vecs_t mapasia_tr7_vecs = { /* we can read and write tracks */
ff_type_file,
{
- ff_cap_none /* waypoints */,
- ff_cap_read /* tracks */,
- ff_cap_none /* routes */
+ ff_cap_none /* waypoints */,
+ ff_cap_read | ff_cap_write /* tracks */,
+ ff_cap_none /* routes */
},
tr7_rd_init,
- NULL,
+ tr7_wr_init,
tr7_rd_deinit,
- NULL,
+ tr7_wr_deinit,
tr7_read,
- NULL,
+ tr7_write,
NULL,
tr7_args,
CET_CHARSET_UTF8, 1 /* FIXED - CET-REVIEW - */